home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
comm
/
async.zip
/
MINT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1986-10-23
|
7KB
|
329 lines
#define LINT_ARGS
#include <stdio.h>
#ifdef MSC
#include <conio.h>
#include <dos.h>
#else
#define inp(x) inportb(x)
#define outp(x,y) outportb(x,y)
#define int86(x,y,z) sysint(x,y,z)
struct WORDREGS {
unsigned int ax;
unsigned int bx;
unsigned int cx;
unsigned int dx;
unsigned int si;
unsigned int di;
unsigned int ds;
unsigned int es;
};
struct BYTEREGS {
unsigned char al, ah;
unsigned char bl, bh;
unsigned char cl, ch;
unsigned char dl, dh;
};
union REGS {
struct WORDREGS x;
struct BYTEREGS h;
};
#endif
#define COMBUFSIZE 2048
#define OUTBUFSIZE 2048
#define TIMEOUT EOF
#define TICKSPERSEC 18
char combuf[COMBUFSIZE];
int inbufin = 0;
int inbufout = 0;
int inchrcnt = 0;
char outbuf[OUTBUFSIZE];
int outchrcnt = 0;
int outbufin = 0,
outbufout = 0;
#ifdef DEBUG
print_status()
{
fprintf(stderr,"\033[s\033[23;20H");
fprintf(stderr,"inbufin=%02d inbufout=%02d inchrcnt=%02d ",
inbufin,inbufout,inchrcnt);
fprintf(stderr,"outbufin=%02d outbufout=%02d outchrcnt=%02d ",
outbufin,outbufout,outchrcnt);
fprintf(stderr,"\033[u");
}
#endif
int comadr;
int comport;
int intnum, intmask, intreg;
#ifdef MSC
unsigned peekw(offset,segment)
unsigned offset,segment;
{
union { unsigned far *ptr; struct { unsigned off, seg } parts } peeker;
peeker.parts.off = offset; peeker.parts.seg = segment;
return *(peeker.ptr);
}
#endif
outbuf_purge()
{
cli();
outchrcnt = outbufin = outbufout = 0;
sti();
}
inbuf_purge()
{
cli();
inchrcnt = inbufin = inbufout = 0;
sti();
}
async_status()
{
return inchrcnt;
}
/*
* timeout_read(timeout)
* waits for data from com port for timeout seconds
*/
unsigned long clock()
{
static union REGS regs;
regs.x.ax = 0;
int86(0x1A,®s,®s);
return ((long)regs.x.dx+((long)regs.x.cx << 16));
}
long timerset(timeout)
int timeout;
{
return (clock() + ((timeout/10)*TICKSPERSEC));
}
int timeup(timer)
long timer;
{
if (timer < clock())
return 1;
return 0;
}
int carrier()
{
/* carrier detect is the msb of the modem status register */
return (inp(comadr+6) & 0x80);
}
unsigned timeout_read(timeout)
int timeout;
{
unsigned long time;
unsigned char async_getc();
if (timeout == 0) /* if they don't want to wait */
return (async_status() ? async_getc() : TIMEOUT);
time = clock();
/* adjust from tenths (about 2 per clock tick) to clock ticks */
time += (long)(timeout << 1);
/* loop until timeout or char ready */
while (time > clock())
{
if (async_status())
return async_getc();
}
return (TIMEOUT);
}
async_putc(c)
unsigned c;
{
/* if output buffer is full then poll till it is */
if (outchrcnt == OUTBUFSIZE)
while(outchrcnt == OUTBUFSIZE)
;
outbuf[outbufin] = c;
if (++outbufin == OUTBUFSIZE)
outbufin = 0;
outchrcnt++;
/* enable data available, tx holding empty */
outp(comadr+1,0x3);
}
unsigned char
async_getc()
{
register unsigned char c;
while(!async_status())
;
c = combuf[inbufout++];
--inchrcnt;
if (inbufout == COMBUFSIZE)
inbufout = 0;
return c;
}
#ifdef MSC
/* #pragma check_stack- */
#endif
void comserv()
{
register unsigned c;
register unsigned int_reason;
outp(0x20,0x20); /* signal non-specific EOI */
/* check for character read */
if (4 == (int_reason = inp(comadr+2)))
{
/* check line status for data ready */
if ( inp(comadr+5) & 0x1 )
{
rcvdata:
c = inp(comadr);
combuf[inbufin++] = c;
if (inbufin == COMBUFSIZE)
inbufin = 0;
++inchrcnt;
}
/* if the transmit holding buffer isn't empty, return */
if ( inp(comadr+5) & 0x20 )
goto snddata;
else
return;
}
/* check for character write */
if (2 == int_reason)
{
if ( inp(comadr+5) & 0x20 )
{
snddata:
if (outchrcnt)
{
outp(comadr,outbuf[outbufout]);
if (++outbufout == OUTBUFSIZE)
outbufout = 0;
if (!--outchrcnt)
/* disable tx holding empty interrupt */
outp(comadr+1,0x1);
}
}
/* check for data ready */
if ( inp(comadr+5) & 0x1 )
goto rcvdata;
else
return;
}
}
#ifdef MSC
/* #pragma check_stack+ */
#endif
async_port_setup(com,baud,parity,wordwidth,stopbits)
{
union REGS regs;
register setup_mask;
register port_mask;
switch(com)
{
case 0: comport = 0; break;
case 1: comport = 1; break;
default: return -1;
}
switch(baud)
{
case 110: setup_mask = 0; break;
case 300: setup_mask = 0x40; break;
case 600: setup_mask = 0x60; break;
case 1200: setup_mask = 0x80; break;
case 2400: setup_mask = 0xA0; break;
case 4800: setup_mask = 0xC0; break;
case 9600: setup_mask = 0xE0; break;
default: return -1;
}
switch (parity)
{
case 0: break;
case 1: setup_mask |= 0x8; break;
case 2: setup_mask |= 0xA; break;
default: return -1;
}
switch (stopbits)
{
case 1: break;
case 2: setup_mask |= 0x4; break;
default: return -1;
}
switch (wordwidth)
{
case 7: setup_mask |= 0x2; break;
case 8: setup_mask |= 0x3; break;
default: return -1;
}
/* call rom bios to set port parms */
regs.x.ax = setup_mask & 0xFF;
regs.x.dx = comport;
int86(0x14,®s,®s);
return 0;
}
async_init(com)
{
register setup_mask;
register port_mask;
switch(com)
{
case 0: comport = 0; intnum = 0xC; intmask = 0xEF; break;
case 1: comport = 1; intnum = 0xB; intmask = 0xF7; break;
default: return -1;
}
/* purge the buffers */
inbuf_purge(); outbuf_purge();
/* set up the communications interrupt */
setup_comint(intnum);
/* get comport base address out of rom bios data segment */
comadr = peekw(comport << 1,0x40);
/* get int enable port mask */
intreg = inp(comadr+1);
/* enable data available */
outp(comadr+1,intreg | 0x1);
/* turn on OUT2 */
outp(comadr+4,0xB);
inp(comadr); inp(comadr); /* two dummy reads to clear status */
port_mask = inp(0x21); /* get int controller mask */
outp(0x21,port_mask & intmask); /* turn on interrupts from com port */
outp(0x20,0x20); /* signal EOI */
return 0;
}
async_restore()
{
register int port_mask;
/* disable com port interrupts */
outp(comadr+1,intreg);
/* get currently masked interrupts */
port_mask = inp(0x21);
/* set the appropriate bit for current com port */
outp(0x21, (port_mask | (intmask ^ 0xFF)));
/* restore interrupt handler */
restore_comint(intnum);
}